package com.weimob.xh.controller.workhf;

import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;

@Controller
@RequestMapping("work/qr/")
public class QRCodeController {

    private static final String TEMPLATE_PATH = "template.png";
    private static final String QRCODE_TEMP = "qrcode_temp";
    private static final String ENDWITH_ZIP_TYPE = ".zip";

    @PostMapping("/generateZip")
    public ResponseEntity<byte[]> generateZip(@RequestParam("file") MultipartFile file) {
        try {
            // 创建临时文件夹
            File tempDir = Files.createTempDirectory(QRCODE_TEMP).toFile();

            // 解压文件
            File uploadedFile = new File(tempDir, file.getOriginalFilename());
            file.transferTo(uploadedFile);

            // 创建 ZIP 文件
            String zipFilePath = tempDir.getAbsolutePath() + File.separator + file.getName() + ENDWITH_ZIP_TYPE;
            ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFilePath));

            // 读取文件中的每个 URL，并生成二维码
            BufferedReader reader = new BufferedReader(new FileReader(uploadedFile));
            String line;
            while ((line = reader.readLine()) != null) {
                generateAndSaveQRCodeWithTemplate(line.trim(), TEMPLATE_PATH, tempDir.getAbsolutePath());
            }
            reader.close();

            // 将文件夹及文件写入 ZIP 文件
            addToZipFile(tempDir.getAbsolutePath(), "", zipOutputStream);
            zipOutputStream.close();

            // 读取 ZIP 文件并返回
            Path zipPath = Paths.get(zipFilePath);
            byte[] zipBytes = Files.readAllBytes(zipPath);

            // 删除临时文件夹
            deleteDirectory(tempDir);

            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            httpHeaders.setContentDispositionFormData("attachment", file.getName() + ENDWITH_ZIP_TYPE);
            return new ResponseEntity<>(zipBytes, httpHeaders, HttpStatus.OK);
//            return ResponseEntity.ok()
//                    .header("Content-Disposition", "attachment; filename=qrcodes.zip")
//                    .body(zipBytes);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }

    private void generateAndSaveQRCodeWithTemplate(String url, String templatePath, String outputFolderPath) throws IOException {
        Map<String, String> parameters = extractParameters(url);
        String schoolId = parameters.get("schoolId");
        String gradeCode = parameters.get("gradeCode");

        String qrCodePath = outputFolderPath + File.separator + schoolId + File.separator + gradeCode;
        String qrCodeFilePath = qrCodePath + File.separator + "qrcodeAndTmp.png";

        File folder = new File(qrCodePath);
        if (!folder.exists()) {
            folder.mkdirs();
        }

        BufferedImage qrCodeImage = generateQRCode(url);
        BufferedImage templateImage = readImage(templatePath);

        // 在模板图片上添加 schoolId 和 gradeCode
        Graphics2D graphics = templateImage.createGraphics();
        graphics.setColor(Color.BLACK);
        graphics.setFont(new Font("Arial", Font.BOLD, 50));
        graphics.drawString(schoolId, 410, 1590);
        graphics.drawString(gradeCode, 410, 1660);
        graphics.dispose();

        // 计算二维码放置位置
        int qrCodeX = 350;
        int qrCodeY = 940;

        // 将二维码放入模板图片中
        BufferedImage resultImage = overlayImages(templateImage, qrCodeImage, qrCodeX, qrCodeY);

        // 保存结果图片
        File qrCodeFile = new File(qrCodeFilePath);
        ImageIO.write(resultImage, "png", qrCodeFile);
    }

    public static BufferedImage readImage(String imagePath) {
        try {
            // 获取图片资源文件
            ClassPathResource resource = new ClassPathResource(imagePath);
            return ImageIO.read(resource.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private BufferedImage generateQRCode(String text) {
        int width = 500;
        int height = 500;

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
            return MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private BufferedImage overlayImages(BufferedImage templateImage, BufferedImage overlayImage, int x, int y) {
        Graphics2D g2d = templateImage.createGraphics();
        g2d.drawImage(overlayImage, x, y, null);
        g2d.dispose();
        return templateImage;
    }

    private Map<String, String> extractParameters(String url) {
        Map<String, String> parameters = new HashMap<>();
        String patternString = "([^?=&]+)(=([^&]*))?";
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(url.substring(url.indexOf("?") + 1));

        while (matcher.find()) {
            String key = matcher.group(1);
            String value = matcher.group(3);
            parameters.put(key, value);
        }

        return parameters;
    }

    private void addToZipFile(String directoryPath, String parentDirectory, ZipOutputStream zipOutputStream) throws IOException {
        File directory = new File(directoryPath);

        // 获取目录中的所有文件及子目录
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    // 递归添加子目录中的文件
                    String subDirectoryPath = parentDirectory + file.getName() + File.separator;
                    addToZipFile(file.getAbsolutePath(), subDirectoryPath, zipOutputStream);
                } else {
                    if (file.getName().endsWith("zip")) {
                        continue;
                    }
                    // 添加文件到 ZIP 文件中
                    byte[] buffer = new byte[1024];
                    FileInputStream inputStream = new FileInputStream(file);
                    zipOutputStream.putNextEntry(new ZipEntry(parentDirectory + file.getName()));
                    int length;
                    while ((length = inputStream.read(buffer)) > 0) {
                        zipOutputStream.write(buffer, 0, length);
                    }
                    inputStream.close();
                }
            }
        }
    }

    private void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file);
                }
            }
        }
        directory.delete();
    }
}